package com.spring.aop.validate;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;

import org.aspectj.lang.JoinPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import com.spring.aop.utils.ReflectionUtils;

/**
 * 数据验证
 * 验证对象被边有注解的属性，并通过递归方式验证对象里的集合，当出现校验失败，对象从集合中移除
 * @author K
 *
 */
public class ValidateCollectionDataRemoveFail {
	private static Logger logger = LoggerFactory.getLogger(ValidateCollectionDataRemoveFail.class);

	public void doBefore(JoinPoint joinPoint) {
		List<Object> store = new ArrayList<>();
		Object[] array = joinPoint.getArgs();
		Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
		for (int i = 0; i < array.length; i++) {
			store.clear();
			if (array[i] instanceof List) {
				store = (List<Object>) array[i];
			} else {
				store.add(array[i]);
			}
			this.validateList(validator, store);
		}
	}
	
	private boolean isValidateSucc(Validator validator, Object object) {
		// 验证某个对象,，其实也可以只验证其中的某一个属性的
		Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object);
		for (ConstraintViolation<Object> constraintViolation : constraintViolations) {
			logger.warn(constraintViolation.getPropertyPath() + ": " + constraintViolation.getMessage());
		}
		//出现校验失败，就返回false
		if (!CollectionUtils.isEmpty(constraintViolations)) {
			return false;
		}
		
		Field[] fields = object.getClass().getDeclaredFields();
		for (Field field : fields) {
			Class<?> clazz = field.getType();
			if (clazz.equals(List.class)) {
				List<Object> tmp = (List<Object>) ReflectionUtils.invokeGetterMethod(object, field.getName());
				//集合为null或size=0时，不进行数据校验
				if (CollectionUtils.isEmpty(tmp)) {
					continue;
				} 
				
				this.validateList(validator, tmp);
				//数据校验完后，集合size=0数据校验失败
				if (tmp.isEmpty()) {
					return false;
				}
			}
		}
		return true;
	}
	
	private void validateList(Validator validator, List<Object> list) {
		Iterator<Object> it = list.iterator();
		while (it.hasNext()) {
			//校验失败的对象从集合中移除
			boolean flag = this.isValidateSucc(validator, it.next());
			if (!flag) {
				it.remove();
			}
		}
	}
}
